/**
 * @file Server.as
 * 最简化 png 文件服务器,
 * @author db0@qq.com
 * @version 1.0.1
 * @date 2017-08-28
 */
package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.ServerSocketConnectEvent;
	import flash.net.ServerSocket;
	import flash.net.Socket;
	import flash.filesystem.*;
	import flash.utils.setTimeout;
	import flash.utils.clearTimeout;
	import flash.utils.ByteArray;

	public class Server extends Sprite
	{
		public static var serverSocket:ServerSocket = new ServerSocket();


		public function Server()
		{
			//this.stage.nativeWindow.activate();
			bind();
		}

		private function onConnect( event:ServerSocketConnectEvent ):void
		{
			var clientSocket:Socket = event.socket;
			clientSocket.addEventListener( ProgressEvent.SOCKET_DATA, onClientSocketData );
			logs.adds( "Connection from " + clientSocket.remoteAddress + ":" + clientSocket.remotePort );
		}

		private var buffer:ByteArray=null;
		private function onClientSocketData( event:ProgressEvent ):void
		{
			var clientSocket:Socket = event.target as Socket;
			if(clientSocket==null)
				return;
			if(buffer==null)
				buffer = new ByteArray();
			clientSocket.readBytes( buffer, buffer.position, clientSocket.bytesAvailable );
			var str:String = buffer.toString();
			if(str.match("\r\n\r\n")==null)
			{
				if(clientSocket){
					clientSocket.flush(); 
					clientSocket.close();
					clientSocket = null;
				}
				buffer.clear();
				buffer = null;
				return;
			}
			str = str.replace(/[\r\n]/img,"");
			var path:String = decodeURI(str.replace(/^GET \/([^ ]+) HTTP\/\d.\d.*$/img,"$1"));
			logs.adds( "path: " + path);
			var bytes:ByteArray = read_bytes(path);
			if(bytes && bytes.length>0){
				sendStr(clientSocket,"HTTP/1.1 200 OK\r\nServer: "+clientSocket.localAddress+"\r\nContent-Type: image/png\r\nAccept-Ranges: bytes\r\nContent-Length: "+bytes.length+"\r\nConnection: keep-alive\r\n\r\n");
				sendBytes(clientSocket,bytes);
				bytes.clear();
			}else{
				sendStr(clientSocket,"HTTP/1.1 404 NOT FOUND\r\nServer: "+clientSocket.localAddress+"\r\nConnection: close\r\n\r\n404");
			}
			logs.adds( "Sent message to " + clientSocket.remoteAddress + ":" + clientSocket.remotePort );
			clientSocket.flush(); 
			clientSocket.close();
			clientSocket = null;
			buffer.position = 0;
			buffer.clear();
			buffer = null;
		}

		public static function read_bytes(filename:String):ByteArray
		{
			var target:File = File.applicationDirectory.resolvePath(filename);
			if(target.exists){
				var bytes:ByteArray = new ByteArray();
				var fileStream:FileStream = new FileStream();
				fileStream.open(target, FileMode.READ);
				fileStream.readBytes(bytes);
				fileStream.close();
				bytes.position = 0;
				//logs.addss.adds("read_bytes",target.nativePath);
				return bytes;
			}
			return null;
		}

		private var timeoutId:uint;
		private function bind(event:Event=null):void
		{
			if( serverSocket.bound ) 
			{
				serverSocket.close();
				serverSocket = new ServerSocket();

			}
			try{
				if(System.isWindows)
				{
					serverSocket.bind(80,"0.0.0.0");
				}else{
					serverSocket.bind(8809,"0.0.0.0");
				}
			}catch(e:Error){
				logs.adds(e);
				/*
				if(System.isWindows)
					Toast.show("port 80 occupied");
				else
					Toast.show("port 8809 occupied");
					*/
				clearTimeout(timeoutId);
				timeoutId = setTimeout(bind,5000);
				return;
			}
			serverSocket.addEventListener( ServerSocketConnectEvent.CONNECT, onConnect );
			serverSocket.listen();
			logs.adds( "Bound to: " + serverSocket.localAddress + ":" + serverSocket.localPort );
			//Toast.show("server OK");
		}

		private function sendStr(clientSocket:Socket, message:String):void
		{
			try
			{
				if( clientSocket != null && clientSocket.connected )
				{
					clientSocket.writeUTFBytes(message);
				}
				else logs.adds("No socket connection.");
			}
			catch ( error:Error )
			{
				logs.adds( error.message );
			}
		}
		private function sendBytes(clientSocket:Socket, message:ByteArray):void
		{
			try
			{
				if( clientSocket != null && clientSocket.connected )
				{
					clientSocket.writeBytes(message);
				}
				else logs.adds("No socket connection.");
			}
			catch ( error:Error )
			{
				logs.adds( error.message );
			}
		}
	}
}



